package com.rightsidetech.commom.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Objects;
import java.util.concurrent.TimeUnit;


@Component
public class RedisUtils {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    RedisTemplate<String,String> redisTemplate;


    /**
     * @param key key
     * @return
     * @Description: 获取自增长值
     */
    public Long getIncr(String key) {
        RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key, Objects.requireNonNull(stringRedisTemplate.getConnectionFactory()));
//        redisAtomicLong.expire(0, TimeUnit.SECONDS);
        return redisAtomicLong.incrementAndGet();
    }

    /**
     * @param key   key
     * @param value 当前值
     * @Description: 初始化自增长值
     */
    public void setIncr(String key, Long value) {
        RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key, Objects.requireNonNull(stringRedisTemplate.getConnectionFactory()));
        redisAtomicLong.set(value);
//        redisAtomicLong.expire(0, TimeUnit.SECONDS);
    }

    /**
     * 将信息 message 发送到指定的频道 channel
     *
     * @param channel
     * @author yhr
     */
    public void publish(String channel, Object message) {
        redisTemplate.convertAndSend(channel, message);
    }

    /**
     * 将信息 message 发送到指定的频道 channel
     *
     * @param channel
     * @author yhr
     */
    public void publishString(String channel, Object message) {
        stringRedisTemplate.convertAndSend(channel, message);
    }


    public boolean getRedisRequestId(String lockName, String val, int expiredSeconds, long acquireTimeoutMilliseconds) throws Exception {
        try {
            // 1.计算获取锁的时间
            Long endTime = System.currentTimeMillis() + acquireTimeoutMilliseconds;
            // 2.尝试获取锁
            while (System.currentTimeMillis() < endTime) {
                // 3. 获取锁成功就设置过期时间
                if (setnx(lockName, val)) {
                    expire(lockName, expiredSeconds);
                    return true;
                }
            }
        } catch (Exception e) {
            throw e;
        }
        return false;
    }

    public Boolean setnx(String key, String value) {
        return stringRedisTemplate.opsForValue().setIfAbsent(key, value);
    }

    public Boolean expire(String key, long timeout) {
        return stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
    }


    /**
     * 将字符串值 value 关联到 key
     */
    public void setex(String key, String value, long timeout, TimeUnit unit) {
        stringRedisTemplate.opsForValue().set(key, value, timeout, unit);
    }

    /**
     * 返回 key所关联的字符串
     */
    public String getex(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }


    /**
     * 读取缓存
     *
     * @param key
     * @return
     */
    public Object get(final String key) {
        Object result = null;
        ValueOperations operations = redisTemplate.opsForValue();
        result = operations.get(key);
        return result;
    }

    /**
     * 写入缓存
     *
     * @param key
     * @param value
     * @param expireTime
     * @param timeUnit
     * @return
     */
    public boolean set(final String key, Object value, Long expireTime, TimeUnit timeUnit) {
        boolean result = false;
        try {
            ValueOperations operations = redisTemplate.opsForValue();
            operations.set(key, value);
            stringRedisTemplate.expire(key, expireTime, timeUnit);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 53
     * 判断key是否存在
     * 54
     *
     * @param key 键
     *            55
     * @return true 存在 false不存在
     * 56
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 67
     * 删除缓存
     * 68
     *
     * @param key 可以传一个值 或多个
     *            69
     */

    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                stringRedisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

}
